package com.pearl.mybatis.demo.excel;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.pearl.mybatis.demo.flex.entity.User;
import com.pearl.mybatis.demo.flex.mapper.UserMapper;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author TangDan
 * @version 1.0
 * @since 2023/5/17
 */
@RestController
@RequestMapping
public class ExcelController {

    @Autowired
    UserMapper userMapper;

    @GetMapping("/export/Hutool")
    public void exportHutool() {
        List<User> userList = userMapper.selectAll(); // 查询用户列表
        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter("d:/用户列表.xlsx");
        // 自定义标题别名
        writer.addHeaderAlias("userName", "姓名");
        writer.addHeaderAlias("userId", "用户ID");
        writer.addHeaderAlias("gender", "性别");
        // 跳过当前行，既第一行，非必须，在此演示用
        writer.passCurrentRow();
        // 一次性写出内容，强制输出标题
        writer.write(userList, true);
        //关闭writer，释放内存
        writer.close();
        // 对于大量数据输出，采用ExcelWriter容易引起内存溢出，因此有了BigExcelWriter，使用方法与ExcelWriter完全一致。
    }

    @GetMapping("/import/Hutool")
    public void importHutool() {
        ExcelReader reader = ExcelUtil.getReader("d:/用户列表.xlsx");
        List<User> all = reader.read(1, 2, User.class);
        System.out.println(all);
    }

    @GetMapping("/export/EasyExcel")
    public void exportEasyExcel(HttpServletResponse response) throws IOException {
        // 最简单的写法
        // 1. Excel对应的实体对象
        List<User> userList = userMapper.selectAll(); // 查询用户列表
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); // 文件的内容类型
        response.setCharacterEncoding("utf-8");
        // 2. 文件名称
        String fileName = URLEncoder.encode("d:/用户列表", StandardCharsets.UTF_8).replaceAll("\\+", "%20"); // 这里URLEncoder.encode可以防止中文乱码
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        // 3. 写出文件
        EasyExcel.write(response.getOutputStream(), User.class).sheet("用户列表").doWrite(userList);
    }


    @GetMapping("/export/Poi")
    public void exportPoi(HttpServletResponse response) throws IOException {
        // 1. Excel对应的实体对象
        List<User> userList = userMapper.selectAll(); // 查询用户列表
        // 2. HSSFWorkbook对象，用于写出为xls格式的Excel
        XSSFWorkbook workbook = new XSSFWorkbook(XSSFWorkbookType.XLSX);
        // 3. 标题
        String[] titles = {"ID", "名字", "性别"};
        // 4. 表格对象
        XSSFSheet sheet = workbook.createSheet("userList");
        // 5. 第一行
        XSSFRow titleRow = sheet.createRow(0);
        // 6. 标题第一行写入数据
        for (int i = 0; i < titles.length; i++) {
            XSSFCell cell = titleRow.createCell(i);// 创建单元格
            cell.setCellValue(titles[i]); // 数据
        }
        // 7. 循环数组，写入数据
        for (int i = 1; i <= userList.size(); i++) {
            // 7.1 创建行，序列1为第二行
            XSSFRow row = sheet.createRow(i);
            // 7.2 写入行
            User user = userList.get(i - 1);
            row.createCell(0).setCellValue(String.valueOf(user.getUserId())); // 第一个单元格
            row.createCell(1).setCellValue(user.getLoginName());// 第二个单元格
            row.createCell(2).setCellValue(String.valueOf(user.getGender()));
        }
        // 8. 响应写出
        response.reset();
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); // 文件的内容类型
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("d:/用户列表", StandardCharsets.UTF_8).replaceAll("\\+", "%20"); // 这里URLEncoder.encode可以防止中文乱码
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        workbook.write(response.getOutputStream());
    }

    /*    *//**
     * 文件导入  实际上就是文件导出反向操作
     *//*
    @Test
    public void test3() throws Exception {
//        1.通过流读取Excel文件
        FileInputStream inputStream = new FileInputStream("/Users/k/Desktop/hhh.xls");
//        2.通过poi解析流 HSSFWorkbook 处理流得到的对象中 就封装了Excel文件所有的数据
        HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
//        3.从文件中获取表对象  getSheetAt通过下标获取
        HSSFSheet sheet = workbook.getSheetAt(0);
//        4.从表中获取到行数据  从第二行开始 到 最后一行  getLastRowNum() 获取最后一行的下标
        int lastRowNum = sheet.getLastRowNum();

        for (int i = 1; i <= lastRowNum; i++) {
//            通过下标获取行
            HSSFRow row = sheet.getRow(i);
//            从行中获取数据

            */

    /**
     * getNumericCellValue() 获取数字
     * getStringCellValue 获取String
     *//*
            double id = row.getCell(0).getNumericCellValue();
            String name = row.getCell(1).getStringCellValue();
            String sex = row.getCell(2).getStringCellValue();

//            封装到对象中
            User user = new User();
            user.setUserId((int) id);
            user.setUserName(name);
            user.setUserSex(sex);

//            将对象添加数据库
            System.out.println(user);
        }
    }*/
    @PostMapping("/import/EasyExcel")
    public String importEasyExcel(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(),
                User.class,
                new PageReadListener<User>(dataList -> {
                    // 默认分页数为100 dataList为当前页数据
                    userMapper.insertBatch(dataList);// 批量插入到数据库中
                })).sheet().doRead();
        return "success";
    }

    @PostMapping("/import/Poi")
    public String importPoi(MultipartFile file) throws IOException {
        // 1. 创建文件对象
        XSSFWorkbook book = new XSSFWorkbook(file.getInputStream());
        XSSFSheet sheet = book.getSheetAt(0);
        int lastRowNum = sheet.getLastRowNum(); // 最后一行的序列号，为 4 ，说明有5行数据
        List<User> userList = new ArrayList<>();
        // 2. 循环每行数据
        for (int i = 0; i < lastRowNum; i++) {
            XSSFRow row = sheet.getRow(i + 1); // 从第二行开始读取
            String rawValue1 = row.getCell(0).getRawValue(); // 第一个单元格
            String rawValue2 = row.getCell(1).getRawValue();
            String rawValue3 = row.getCell(2).getRawValue();
            User user=new User();
            user.setUserId(Long.valueOf(rawValue1));
            user.setLoginName(rawValue2);
            user.setGender(Integer.valueOf(rawValue3));
            userList.add(user);
        }
        // 3. 入库
        book.close();
        System.out.println(userList);
        return "success";
    }
}
